package top.yangguangmc.sunshine_anticheat.check.action;

import org.jetbrains.annotations.NotNull;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class Action implements Comparable<Action> {
    public static final String REGEX = "\\[\\d+:\\d+/\\w{1,10}](\\w|\\W)*";
    private final int baseVL;
    private final int everyVL;
    private final ActionType type;
    private final List<String> value = new ArrayList<>(5);

    public Action(int baseVL, int everyVL, ActionType type, String value) {
        this.baseVL = Math.max(baseVL, 0);
        this.everyVL = Math.max(everyVL, 0);
        this.type = type == null ? ActionType.CMD : type;
        this.value.add(value == null ? "" : value);
    }

    public List<String> getValue() {
        return value;
    }

    public ActionType getType() {
        return type;
    }

    public int getEveryVL() {
        return everyVL;
    }

    public int getBaseVL() {
        return baseVL;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Action action = (Action) o;
        return baseVL == action.baseVL && everyVL == action.everyVL && type == action.type && Objects.equals(value, action.value);
    }

    @Override
    public int hashCode() {
        return Objects.hash(baseVL, everyVL, type, value);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (String s : value) sb.append(s).append("; ");
        if (sb.length() > 1) sb.deleteCharAt(sb.length() - 1).deleteCharAt(sb.length() - 1);
        return String.format("[%d:%d/%s] %s", baseVL, everyVL, type.name(), sb);
    }

    @Override
    public int compareTo(@NotNull Action o) {
        return Integer.compare(o.getType().getPerformPriority(), type.getPerformPriority());
    }

    public static Action of(String actionString) throws ParseException {
        //Format: [baseVL:everyVL/ActionType] Values...
        if (actionString == null || actionString.trim().isEmpty())
            throw new ParseException("Empty string \"" + actionString + "\".", -2);
        if (!actionString.trim().matches(REGEX))
            throw new ParseException("Format mismatch! Regex: \"" + REGEX + "\".", -1);
        int errOffset = 0;
        try {
            int baseVL = Integer.parseInt(actionString.substring(1, actionString.indexOf(":")));
            errOffset = actionString.indexOf(":") + 1;
            int everyVL = Integer.parseInt(actionString.substring(actionString.indexOf(":") + 1, actionString.indexOf("/")));
            errOffset = actionString.indexOf("/") + 1;
            ActionType type = ActionType.valueOf(actionString.substring(actionString.indexOf("/") + 1, actionString.indexOf("]")).toUpperCase().trim());
            errOffset = actionString.indexOf("]") + 1;
            String value = actionString.substring(actionString.indexOf("]") + 1).trim();
            return new Action(baseVL, everyVL, type, value);
        } catch (IllegalArgumentException e) {
            throw new ParseException(errOffset <= actionString.indexOf("/") ? "Invalid number format."
                    : "Invalid action type name.", errOffset);
        }
    }
}
